/*
 * @Desc 许继保设备作为 TCP 服务端开放2404端口
 * 本侧连接到保护装置作为客户端，
 * 1. 每次发送消息带有asdu ，使用 apci I 帧格式
 * 2. 发送状态计数器，和接收状态计数器要动态自加1
 * */

#ifndef XJCONNECTION_H
#define XJCONNECTION_H

#include <QTcpSocket>
#include <QObject>
#include <QTimer>
#include "XJ/XJ103Constructer.h"
#include "utils.h"
#include <QMessageBox>
#include <QUdpSocket>       // 四方可能是 UDP 方式

#define XJ_SEND_INTERVEAL 100

enum  {
    IFrame,
    SFrame,
    UFrame
};

class XJConnection:public QObject
{
    Q_OBJECT
public:
   XJConnection();

   virtual ~XJConnection();

   void setIPPortAndConnect(const QString &destDevIp, const QString &localIp, const QString &port);
   void connectToDevice();         // 连接到保护设备服务器
   void sendTcpMsg(QString &msg);  // 发送tcp消息到保护服务端
   void sendTcpMsg(QByteArray &msg);  // 发送tcp消息到保护服务端
   void sendTcpMsgI(QByteArray &msg);   //  发送 I 帧 含有信息数据报文
   void sendTcpMsg(const QByteArrayList &msgList);  // 发消息队列

   QByteArray getRecvTcpMsg();
   QByteArray getRecvMsg();         // 返回接受缓冲区的内容
   void disconnectFromDevice();

   void startHeartTimer();
   void stopHeartTimer();

   QStringList getLocalHostIPList();

   void sendUdpMsg(QByteArray &msg);  // 发送tcp消息到保护服务端
   bool bindUdp();

signals:
    void sig_readyRead();
    void sig_disconnect();
    void sig_conncted();                // tcp 客户端段连接服务端成功
    void sig_sendMsg(QString);           // 回馈给测试 UI界面添加显示已经发送的消息
    void sig_sendCMDListFinished();     //工作线程通知完成消息队列发送任务

public slots:
    void slot_socketDisconnected();
    void slot_recvTcpMsg();
    void slot_connectSuccess();     // 连接成功设置client状态为 true
    void slot_sendHeartBeatMsg();

    void slot_connectDevice();

    void slot_sendTcpMsgList();

    // udp
    void slot_sendUdpMsgList();
    void slot_recvUdpMsg();

    /* @Des 判断接收到的报文的apci 的格式
     *  返回值： 0表示I， 1 表示S，2 表示U
     * */
    int ApciFormatJudge(QByteArray msg);

private:
    void displayError(QAbstractSocket::SocketError socketError);

private:
    QTcpSocket *m_tcpClientSocket;
    QUdpSocket *m_udpClientSocket;

    // 通信参数
    QString m_port;         // 保护的监听端口
    QString m_localAddr;    // 本机与保护通讯的ip地址
    QString m_localAddrLastPart;    // 本机地址的最后一段，192.168.0.35，0x2300占两个字节
    QString m_destDevAddr;   //保护设备的ip地址，目标设备地址
    QString m_destDevAddrLastPart; // 目标设备地址 ，占两个字节

    QString m_srcDevAddr;   // 从m_local中取最后一个字段 ，占两个字节
    QString m_cpuAddr; //通过分割 m_destDevAddr获取，在asdu中使用，占一个字节

    QByteArray m_recvBuffer;     // 消息接收缓冲区
    XJ103Constructer *m_packetConstructer;
    QTimer m_heartTimer;    // tcp 心跳报文

    int m_dataSendNo = 0; // 每次发送消息， 发送序号 apci 的消息编号自增一次,初始值为0；
    int m_dataRecvNo = 0;   // 接收序号, 报文 apci I帧控制域定义构造用到

    QTimer m_timerConnct;
    int m_connectTimeLimit;     // 配置连接超时次数，每次点击连接的时候置为10

    QTimer m_timerSendCmdList; //
    int  m_indexSendCmdList = 0;    // 发送命令队列的序号

    QByteArrayList m_cmdListReadBill;    //读取信息的命令序列
};

#endif // XJCONNECTION_H
